//
//  HACRouterPath.m
//  HACRouter
//
//  Created by Chengjie on 2019/5/3.
//

#import "HACRouterPath.h"

@interface HACRouterPath ()
@property (nonatomic, strong) NSURL *url;
@property (nonatomic, copy) NSString *urls;
@property (nonatomic, copy) NSString *pathName;
@property (nonatomic, copy) NSString *urlHost;
@property (nonatomic, copy) NSString *urlScheme;
@property (nonatomic, strong) NSMutableDictionary<NSString *, NSString *> *parameters;
@end

@implementation HACRouterPath

/**
 合法性校验： scheme 和 host 是否在配置的白名单列表内
 */
+ (BOOL)verifyScheme:(NSString *)scheme host:(NSString *)host  whiteHosts:(NSSet<NSString *> *)hosts whiteSchemes:(NSSet<NSString *> *)schemes {
    if (!scheme || ![schemes containsObject:scheme]) {
        return NO;
    }
    if (!host || ![hosts containsObject:host]) {
        return NO;
    }
    return YES;
}

+ (instancetype)routerPathWithUrls:(NSString *)urls whiteHosts:(NSSet<NSString *> *)hosts whiteSchemes:(NSSet<NSString *> *)schemes {
    if (!urls || ![urls isKindOfClass:[NSString class]] || !urls.length) {
        return nil;
    }
    // 校验合法性
    NSString *hString = [urls lowercaseString];
    NSURL *url = [NSURL URLWithString:hString];
    BOOL verify = [self verifyScheme:url.scheme host:url.host whiteHosts:hosts whiteSchemes:schemes];
    if (!verify) {
        return nil;
    }
    
    HACRouterPath *path = [[HACRouterPath alloc] init];
    path.url = url;
    path.urls = url.absoluteString;
    path.pathName = url.relativePath;
    path.urlHost = url.host;
    path.urlScheme = url.scheme;
    
    NSString *routerName = [path.pathName stringByReplacingOccurrencesOfString:@"/" withString:@"_"];
    if ([routerName hasPrefix:@"_"]) {
        path.routerName = [routerName substringFromIndex:1];
    } else {
        path.routerName = routerName;
    }
    NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
    if (!url.absoluteString || !url.absoluteString.length) {
        return path;
    }
    // 提取参数
    NSURLComponents *urlComponents = [[NSURLComponents alloc] initWithString:url.absoluteString];
    [urlComponents.queryItems enumerateObjectsUsingBlock:^(NSURLQueryItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        [parameters setValue:obj.value forKey:obj.name];
    }];
    path.parameters = parameters;
    return path;
}

+ (instancetype)routerPathWithUrls:(NSString *)urls whiteHosts:(NSSet<NSString *> *)hosts whiteSchemes:(NSSet<NSString *> *)schemes customParser:(nullable id<HACRouterUrlParserRules>)parser {
    if (!parser || ![parser conformsToProtocol:@protocol(HACRouterUrlParserRules)]) {
        return [self routerPathWithUrls:urls whiteHosts:hosts whiteSchemes:schemes];
    }
    if (!urls || ![urls isKindOfClass:[NSString class]] || !urls.length) {
        return nil;
    }
    
    // 校验合法性
    NSString *scheme = [parser parseSchemeFromUrls:urls];
    NSString *host = [parser parseHostFromUrls:urls];
    BOOL verify = [self verifyScheme:scheme host:host whiteHosts:hosts whiteSchemes:schemes];
    if (!verify) {
        return nil;
    }
    
    HACRouterPath *path = [[HACRouterPath alloc] init];
    path.urls = urls;
    if ([parser respondsToSelector:@selector(parseUrlFromUrls:)]) {
        path.url = [parser parseUrlFromUrls:urls];
    }
    if ([parser respondsToSelector:@selector(parsePathNameFromUrls:)]) {
        path.pathName = [parser parsePathNameFromUrls:urls];
    }
    path.urlHost = host;
    path.urlScheme = scheme;
    path.routerName = [parser parseRouterNameFromUrls:urls];
    path.parameters = [parser parseParametersFromUrls:urls];
    return path;
}

- (void)figureBestInitSelectorAndArgumentsInSelList:(NSArray<NSString *> *)selList {
    if (selList.count <= 1) {
        self.bestInitSelector = [selList firstObject];
    } else {
        NSArray *allKeys = [self.parameters allKeys];
        __block NSInteger matchCount = 0;
        __block NSInteger matchIndex = 0;
        [selList enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            NSArray<NSString *> *bsetAvgs = [self pickOutArgumentsFromSelName:obj];
            NSInteger currentCount = 0;
            for (NSString *avg in bsetAvgs) {
                if ([allKeys containsObject:avg]) {
                    currentCount++;
                }
            }
            if (currentCount > matchCount) {
                matchCount = currentCount;
                matchIndex = idx;
            }
        }];
        self.bestInitSelector = [selList objectAtIndex:matchIndex];
    }
    
    [self figureBestArguments];
    
}

- (void)figureBestArguments {
    NSMutableArray<NSString *> *avgNames = [self pickOutArgumentsFromSelName:self.bestInitSelector];
    if (!avgNames || !avgNames.count) {
        return;
    }
    NSMutableArray *bsetAvgs = [NSMutableArray arrayWithCapacity:avgNames.count];
    [avgNames enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        [bsetAvgs addObject:[self.parameters valueForKey:obj] ?: @""];
    }];
    self.bestInitArgs = bsetAvgs;
}

- (NSMutableArray<NSString *> *)pickOutArgumentsFromSelName:(NSString *)selName {
    NSArray<NSString *> *avgs = [selName componentsSeparatedByString:@":"];
    if (avgs.count <= 1) {
        return nil;
    }
    NSMutableArray *resultAvgs = [NSMutableArray array];
    [avgs enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if (idx > 0) {
            if (obj.length) {
                [resultAvgs addObject:obj];
            }
        } else {
            NSString *firstAvg = [[obj componentsSeparatedByString:@"_"] lastObject];
            [resultAvgs addObject:firstAvg];
        }
    }];
    return resultAvgs;
}

@end
